﻿using System;
using System.Collections.Generic;
using System.Data.Linq.Mapping;
using System.Linq.Expressions;
using BReusable.StaticReflection;

namespace BReusable
{
	public static class Linq
	{

		/// <summary>
		/// From BReusable
		/// </summary>
		/// <param name="type">TEntity type</param>
		/// <returns></returns>
		/// <remarks>http://www.codeproject.com/KB/cs/LinqColumnAttributeTricks.aspx</remarks>
		public static List<ColumnAttribute> GetColumnAttributes(Type type)
		{
			var result = new List<ColumnAttribute>();
			System.Reflection.PropertyInfo[] prop = type.GetProperties();
			foreach (var item in prop)
			{
				var info = item.GetCustomAttributes(typeof(ColumnAttribute), true);
				if (info.Length == 1)
				{
					var ca = (ColumnAttribute)info[0];
					result.Add(ca);
				}
				else ("property had more than 1 column Attribute:" + item.Name).ToDebug();
			}
			return result;

		}
		/// <summary>
		/// From BReusable
		/// </summary>
		/// <typeparam name="TEntity"></typeparam>
		/// <returns></returns>
		/// <remarks>http://www.codeproject.com/KB/cs/LinqColumnAttributeTricks.aspx</remarks>
		public static List<ColumnAttribute> GetColumnAttributes<TEntity>()
		{

			var result = new List<ColumnAttribute>();
			System.Reflection.PropertyInfo[] prop = typeof(TEntity).GetProperties();
			foreach (var item in prop)
			{
				var info = item.GetCustomAttributes(typeof(ColumnAttribute), true);
				if (info.Length == 1)
				{
					var ca = (ColumnAttribute)info[0];
					result.Add(ca);
				}
				else ("property had more than 1 column Attribute:" + item.Name).ToDebug();
			}
			return result;

		}

		/// <summary>
		/// Uses an extra parameter to help with design-time and compile-time literal 
		/// doesn't as easily get out of sync with the db
		/// Usage example:
		/// var columnInfo = Linq.GetColumnAttribute&lt;zApplication&gt;(Member.Name&lt;zApplication&gt;(item=>item.lastUser));
		/// </summary>
		/// <typeparam name="TEntity">Should be your linq entity</typeparam>
		/// <param name="fieldName"></param>
		/// <returns></returns>
		public static ColumnAttribute GetColumnAttribute<TEntity>(string fieldName)
		{
			System.Reflection.PropertyInfo prop = typeof(TEntity).GetProperty(fieldName);
			var info = prop.GetCustomAttributes(typeof(ColumnAttribute), true);
			if (info != null && info.Length == 1)
			{
				return (ColumnAttribute)info[0];
			}
			return null;
		}

		///// <summary>
		///// Uses an extra parameter to help with design-time and compile-time literal 
		///// doesn't as easily get out of sync with the db
		///// Usage example:
		///// var columnInfo = Linq.GetColumnAttribute&lt;zApplication>(item => item.lastUser);
		///// </summary>
		//public static ColumnAttribute GetColumnAttribute<TEntity>(Expression<Action<TEntity>> fieldNameExpression)
		//{
		//    var fieldName = Member.StaticValueName<TEntity>(fieldNameExpression);
		//    return GetColumnAttribute<TEntity>(fieldName);
		//}

		/// <summary>
		/// Uses an extra parameter to help with design-time and compile-time literal 
		/// doesn't as easily get out of sync with the db
		/// Usage example:
		/// var columnInfo = Linq.GetColumnAttribute&lt;zApplication>( item => item.lastUser);
		/// </summary>
		public static ColumnAttribute GetColumnAttribute<TEntity>(Expression<Func<object>> fieldNameExpression)
		{
			var fieldName = Member.StaticValueName(fieldNameExpression);
			return GetColumnAttribute<TEntity>(fieldName);
		}

	}
}
